﻿using AsmShaderConverter.HlslShader;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AsmShaderConverter.AsmShader
{
    public class Register : IConvertToHlsl
    {
        private EnumVariableTypes enumVariableTypes;
        private readonly string registerName;
        public char[] swizzle = new char[4];
        public bool halfPrecison;

        private bool IsAbsValue;
        private bool IsNegative;
        public Register GetDestinationRegister()
        {
            return this;
        }

        public string OriginalRegisterName { get { return this.registerName; } }
        public string GetRegisterName(AsmShaderFile asmShader)
        {
            string returnString = string.Format("{0}", this.registerName.ToString());

            ExportRegisterNames exportRegister;
            if (asmShader.GetExportRegister(this.registerName, out exportRegister))
                returnString = string.Format("{0}", exportRegister.ExportName);

            return returnString;
        }

        public Register(string register, char[] destinationSwizzle)
            : this(register, false, destinationSwizzle)
        {

        }
        public Register(string register, bool halfPrecison, char[] destinationSwizzle)
        {
            this.halfPrecison = halfPrecison;

            var stringSplit = register.Split('.');

            string registerName = stringSplit[0];

            if (registerName.EndsWith("_abs"))
            {
                registerName = registerName.Replace("_abs", "");
                IsAbsValue = true; // throw new Exception("_abs not implemented! " + registerName);
            }

            if (registerName.StartsWith("-"))
            {
                IsNegative = true;
                registerName = registerName.Replace("-", "");
            }

            switch (stringSplit.Length)
            {
                case 1:
                    this.registerName = registerName;
                    this.swizzle = new char[] { 'x', 'y', 'z', 'w' };
                    break;
                case 2:
                    this.registerName = registerName;
                    swizzle = stringSplit[1].ToCharArray();
                    break;
                default:
                    throw new Exception("Kann register nicht erzeugen. " + register);
            }

            this.swizzle = Swizzle.CorrectSwizzle(this.swizzle, destinationSwizzle);
        }

        public string ToHLSL(AsmShaderFile asmShader)
        {
            string swizzle = new string(this.swizzle).Replace("\0", "");


            AsmShaderConverter.AsmShader.ExportRegisterNames exportRegister;
            string returnString;
            if (asmShader.GetExportRegister(this.registerName, out exportRegister))
            {
                returnString = string.Format("{0}.{1}", exportRegister.ExportName, Swizzle.GetSwizzle(HlslShaderType.GetHlslType(exportRegister.typeName), exportRegister.offset, swizzle.ToCharArray()));
            }
            else
            {
                // Add swizzles
                if (swizzle != string.Empty)
                    swizzle = "." + swizzle;
                returnString = string.Format("{0}{1}", this.registerName.ToString(), swizzle);
            }

            if (IsAbsValue)
                returnString = "abs(" + returnString + ")";
            if (IsNegative)
                returnString = "-" + returnString;

            return returnString;
        }

        internal string GetNameWithNewSwizzle(string swizzle, AsmShaderFile asmShader)
        {
            string exportRegistername = this.registerName.ToString();


            if (swizzle == string.Empty)
                throw new Exception("No swizzle given! ");

            AsmShaderConverter.AsmShader.ExportRegisterNames exportRegister;
            HlslTypes type = HlslTypes.float1;
            int offset = 0;
            if (asmShader.GetExportRegister(this.OriginalRegisterName, out exportRegister))
            {
                exportRegistername = exportRegister.ExportName;
                type = HlslShaderType.GetHlslType(exportRegister.typeName);
                offset = exportRegister.offset;
            }

            string returnString = string.Format("{0}.{1}", exportRegistername, Swizzle.GetSwizzle(type, offset, swizzle.ToCharArray()));
            if (IsAbsValue)
                returnString = "abs(" + returnString + ")";
            if (IsNegative)
                returnString = "-" + returnString;

            return returnString;
        }

        public string ToHLSLWitchComment(AsmShaderFile asmShader)
        {
            return this.ToHLSL(asmShader);
        }

    }
}
